package qy.jalgotrade.utils.plotter;

import java.lang.reflect.InvocationTargetException;
import java.time.ZonedDateTime;
import java.util.Arrays;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import qy.jalgotrade.bar.Bar;
import qy.jalgotrade.bar.Bars;
import qy.jalgotrade.broker.Broker;
import qy.jalgotrade.broker.Order;
import qy.jalgotrade.broker.OrderEvent;
import qy.jalgotrade.broker.OrderExecutionInfo;

/**
 * A Subplot responsible for plotting an instrument.
 * 
 * @author c-geo
 *
 */
public class InstrumentSubplot extends Subplot {

	private static final Logger logger = LoggerFactory.getLogger(InstrumentSubplot.class);

	private final String __instrument;

	private final boolean __plotBuySell;

	private final Series<Bar, Double> __instrumentSeries;

	/**
	 * 
	 * @param instrument instrument
	 * @param frequency frequency
	 * @param plotBuySell plotBuySell
	 */
	public InstrumentSubplot(String instrument, Bar.Frequency frequency, boolean plotBuySell) {

		super(frequency);
		__instrument = instrument;
		__plotBuySell = plotBuySell;
		try {
			__instrumentSeries = getSeries(instrument, InstrumentMarker.class);
		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException
		        | InstantiationException e) {
			logger.error("Exception occured creating InstrumentMarker: {}", ExceptionUtils.getStackTrace(e));
			throw new IllegalStateException(e);
		}
	}

	/**
	 * 
	 * @param useAdjClose useAdjClose
	 */
	public void setUseAdjClose(boolean useAdjClose) {

		((InstrumentMarker) __instrumentSeries).setUseAdjClose(useAdjClose);
	}

	/*
	 * (non-Javadoc)
	 * @see qy.jalgotrade.utils.plotter.Subplot#onBars(qy.jalgotrade.bar.Bars)
	 */
	@Override
	public void onBars(Bars bars) {

		super.onBars(bars);
		Bar bar = bars.getBar(__instrument);
		if (bar != null) {
			ZonedDateTime dateTime = bars.getDateTime();
			__instrumentSeries.addValue(dateTime, bar);
		}
	}

	/**
	 *
	 * @param broker broker
	 * @param orderEvent orderEvent
	 */
	public void onOrderEvent(Broker broker, OrderEvent orderEvent) {

		Order order = orderEvent.getOrder();
		if (__plotBuySell && Arrays.asList(OrderEvent.Type.PARTIALLY_FILLED, OrderEvent.Type.FILLED)
		        .contains(orderEvent.getEventType()) && __instrument.equals(order.getInstrument())) {

			try {

				Order.Action action = order.getAction();
				OrderExecutionInfo execInfo = orderEvent.getEventInfo();
				if (Arrays.asList(Order.Action.BUY, Order.Action.BUY_TO_COVER).contains(action)) {

					getSeries("Buy", BuyMarker.class).addValue(execInfo.getDateTime(), execInfo.getPrice());
				} else { // action in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]:

					getSeries("Sell", SellMarker.class).addValue(execInfo.getDateTime(), execInfo.getPrice());
				}
			} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException
			        | InstantiationException e) {

				logger.error("Exception occured creating BuyMarker / SellMarker: {}", ExceptionUtils.getStackTrace(e));
			}
		}
	}
}
